/**
 * @file protocol_statemachine.h
 * @brief 104协议状态机管理器头文件
 * @details 本文件定义了104协议的状态机管理功能，包括状态机创建、销毁、启动、停止、
 *          事件处理、状态查询、回调设置、超时管理等核心功能。实现完整的104协议状态机逻辑，
 *          支持多种状态（STOPPED、STARTING、STARTED、STOPPING、ERROR）和子状态管理，
 *          提供线程安全的状态机操作接口。
 * 
 * @author zyb
 * @date 2025-10-14
 * @version 1.0
 */

#ifndef PROTOCOL_STATEMACHINE_H
#define PROTOCOL_STATEMACHINE_H

#include "../../common/types/include/protocol_types.h"
#include "../../common/error/include/error_codes.h"
#include <stdint.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

/* ==================== 104协议状态定义 ==================== */

/**
 * @brief 104协议连接状态
 */
typedef enum {
    PROTOCOL_STATE_STOPPED = 0,        /* 停止状态 */
    PROTOCOL_STATE_STARTING,           /* 启动状态 */
    PROTOCOL_STATE_STARTED,            /* 已启动状态 */
    PROTOCOL_STATE_STOPPING,           /* 停止中状态 */
    PROTOCOL_STATE_ERROR               /* 错误状态 */
} protocol_state_t;

/**
 * @brief 104协议连接子状态
 */
typedef enum {
    PROTOCOL_SUBSTATE_IDLE = 0,        /* 空闲子状态 */
    PROTOCOL_SUBSTATE_CONNECTING,      /* 连接中子状态 */
    PROTOCOL_SUBSTATE_CONNECTED,       /* 已连接子状态 */
    PROTOCOL_SUBSTATE_DISCONNECTING,   /* 断开中子状态 */
    PROTOCOL_SUBSTATE_DATA_TRANSFER    /* 数据传输子状态 */
} protocol_substate_t;

/**
 * @brief 104协议事件类型
 */
typedef enum {
    PROTOCOL_EVENT_START = 0,          /* 启动事件 */
    PROTOCOL_EVENT_STOP,               /* 停止事件 */
    PROTOCOL_EVENT_CONNECT,            /* 连接事件 */
    PROTOCOL_EVENT_DISCONNECT,         /* 断开事件 */
    PROTOCOL_EVENT_DATA_RECEIVED,      /* 数据接收事件 */
    PROTOCOL_EVENT_DATA_SENT,          /* 数据发送事件 */
    PROTOCOL_EVENT_TIMEOUT,            /* 超时事件 */
    PROTOCOL_EVENT_ERROR               /* 错误事件 */
} protocol_event_t;

/* ==================== 状态机配置 ==================== */

/**
 * @brief 状态机配置
 */
typedef struct {
    uint32_t t0_timeout;               /* T0超时时间(ms) */
    uint32_t t1_timeout;               /* T1超时时间(ms) */
    uint32_t t2_timeout;               /* T2超时时间(ms) */
    uint32_t t3_timeout;               /* T3超时时间(ms) */
    uint16_t k_value;                  /* K值(最大未确认I格式帧数) */
    uint16_t w_value;                  /* W值(最大未确认接收帧数) */
    bool auto_reconnect;               /* 自动重连 */
    uint32_t max_retry_count;          /* 最大重试次数 */
} protocol_statemachine_config_t;

/* ==================== 状态机统计 ==================== */

/**
 * @brief 状态机统计信息
 */
typedef struct {
    uint64_t state_changes;            /* 状态变化次数 */
    uint64_t events_processed;         /* 处理的事件数 */
    uint64_t timeouts_occurred;        /* 超时次数 */
    uint64_t errors_occurred;          /* 错误次数 */
    uint64_t reconnections;            /* 重连次数 */
    uint32_t current_retry_count;      /* 当前重试次数 */
} protocol_statemachine_stats_t;

/* ==================== 状态机句柄 ==================== */

/**
 * @brief 协议状态机句柄
 */
typedef struct protocol_statemachine* protocol_statemachine_handle_t;

/* ==================== 回调函数类型 ==================== */

/**
 * @brief 状态变化回调函数
 */
typedef void (*protocol_state_callback_t)(protocol_state_t old_state, 
                                         protocol_state_t new_state, 
                                         void* user_data);

/**
 * @brief 事件处理回调函数
 */
typedef protocol_error_t (*protocol_event_callback_t)(protocol_event_t event, 
                                                     const void* event_data, 
                                                     void* user_data);

/**
 * @brief 超时回调函数
 */
typedef void (*protocol_statemachine_timeout_callback_t)(uint32_t timeout_type, 
                                           void* user_data);

/* ==================== 状态机管理函数 ==================== */

/**
 * @brief 创建协议状态机管理器
 * @details 创建并初始化一个新的协议状态机管理器实例。该函数会验证配置参数，
 *          分配内存，初始化状态机状态，设置超时配置，并创建互斥锁。
 *          创建成功后，状态机处于STOPPED状态，需要调用start函数启动。
 * 
 * @param config 状态机配置参数，不能为NULL
 * 
 * @return 状态机管理器句柄
 *         - 成功：返回有效的句柄
 *         - 失败：返回NULL（配置无效或内存分配失败）
 * 
 * @note 该函数是线程安全的
 * @note 创建后状态机处于STOPPED状态
 * @warning 返回的句柄需要在使用完毕后调用destroy函数释放
 * @see protocol_statemachine_config_t
 * @see protocol_statemachine_destroy
 * @see protocol_statemachine_start
 */
protocol_statemachine_handle_t protocol_statemachine_create(const protocol_statemachine_config_t* config);

/**
 * @brief 销毁协议状态机管理器
 * @details 销毁协议状态机管理器，释放所有相关资源。该函数会先停止状态机，
 *          然后销毁互斥锁，最后释放内存。销毁后，句柄将不再有效，不应再使用。
 * 
 * @param handle 状态机管理器句柄，不能为NULL
 * 
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 销毁成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 句柄为空指针
 * 
 * @note 该函数是线程安全的，会先停止状态机再销毁资源
 * @note 销毁后，句柄将不再有效，不应再使用
 * @warning 销毁后，所有相关的状态机操作都将失败
 * @see protocol_statemachine_create
 * @see protocol_statemachine_stop
 */
protocol_error_t protocol_statemachine_destroy(protocol_statemachine_handle_t handle);

/**
 * @brief 启动协议状态机管理器
 * @details 启动协议状态机管理器，开始状态机的运行。该函数会设置运行标志，
 *          启动超时处理线程，并将状态机转换到STARTING状态。如果状态机已经在运行，
 *          则直接返回成功。
 * 
 * @param handle 状态机管理器句柄，不能为NULL
 * 
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 启动成功或已经在运行
 *         - PROTOCOL_ERROR_NULL_POINTER: 句柄为空指针
 *         - PROTOCOL_ERROR_SYSTEM_INIT_FAILED: 系统初始化失败（线程创建失败）
 * 
 * @note 该函数是线程安全的，使用互斥锁保护共享数据
 * @note 如果状态机已经在运行，函数会直接返回成功
 * @note 启动后会创建超时处理线程
 * @warning 启动失败时，状态机会保持停止状态
 * @see protocol_statemachine_stop
 * @see protocol_statemachine_timeout_thread
 */
protocol_error_t protocol_statemachine_start(protocol_statemachine_handle_t handle);

/**
 * @brief 停止协议状态机管理器
 * @details 停止协议状态机管理器，结束状态机的运行。该函数会设置停止标志，
 *          停止超时处理线程，并将状态机转换到STOPPING状态，然后等待线程结束，
 *          最后转换到STOPPED状态。如果状态机已经停止，则直接返回成功。
 * 
 * @param handle 状态机管理器句柄，不能为NULL
 * 
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 停止成功或已经停止
 *         - PROTOCOL_ERROR_NULL_POINTER: 句柄为空指针
 * 
 * @note 该函数是线程安全的，使用互斥锁保护共享数据
 * @note 如果状态机已经停止，函数会直接返回成功
 * @note 停止过程包括等待超时处理线程结束
 * @warning 停止后，状态机将不再处理事件
 * @see protocol_statemachine_start
 * @see protocol_statemachine_timeout_thread
 */
protocol_error_t protocol_statemachine_stop(protocol_statemachine_handle_t handle);

/**
 * @brief 处理协议状态机事件
 * @details 处理协议状态机事件，根据当前状态和事件类型进行相应的状态转换。
 *          该函数会先检查状态机是否正在运行，然后调用事件处理回调函数，
 *          最后根据事件和当前状态进行状态转换。该函数是状态机的核心处理函数。
 * 
 * @param handle 状态机管理器句柄，不能为NULL
 * @param event 要处理的事件类型
 * @param event_data 事件数据，可以为NULL
 * 
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 事件处理成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 句柄为空指针
 *         - PROTOCOL_ERROR_SYSTEM_NOT_READY: 状态机未运行
 *         - 其他错误码：来自事件处理回调函数
 * 
 * @note 该函数是线程安全的，使用互斥锁保护共享数据
 * @note 事件处理包括回调函数调用和状态转换
 * @note 如果状态机未运行，函数会返回错误
 * @warning 事件处理回调函数应该尽快返回，避免阻塞状态机
 * @see protocol_event_t
 * @see protocol_statemachine_handle_event
 */
protocol_error_t protocol_statemachine_process_event(protocol_statemachine_handle_t handle, 
                                                    protocol_event_t event, 
                                                    const void* event_data);

/* ==================== 状态查询函数 ==================== */

/**
 * @brief 获取协议状态机当前主状态
 * @details 获取协议状态机管理器的当前主状态。该函数是线程安全的，
 *          使用互斥锁保护共享数据的访问。
 * 
 * @param handle 状态机管理器句柄，不能为NULL
 * 
 * @return 当前主状态
 *         - 如果句柄为NULL，返回PROTOCOL_STATE_ERROR
 *         - 否则返回当前主状态
 * 
 * @note 该函数是线程安全的
 * @see protocol_state_t
 * @see protocol_statemachine_get_substate
 */
protocol_state_t protocol_statemachine_get_state(protocol_statemachine_handle_t handle);

/**
 * @brief 获取协议状态机当前子状态
 * @details 获取协议状态机管理器的当前子状态。该函数是线程安全的，
 *          使用互斥锁保护共享数据的访问。
 * 
 * @param handle 状态机管理器句柄，不能为NULL
 * 
 * @return 当前子状态
 *         - 如果句柄为NULL，返回PROTOCOL_SUBSTATE_IDLE
 *         - 否则返回当前子状态
 * 
 * @note 该函数是线程安全的
 * @see protocol_substate_t
 * @see protocol_statemachine_get_state
 */
protocol_substate_t protocol_statemachine_get_substate(protocol_statemachine_handle_t handle);

/**
 * @brief 获取协议状态机统计信息
 * @details 获取协议状态机管理器的统计信息，包括各种操作的计数和状态。
 *          该函数会复制当前的统计信息到提供的缓冲区中，应用程序可以查看
 *          状态机管理器的运行状态。该函数是线程安全的，使用互斥锁保护。
 * 
 * @param handle 状态机管理器句柄，不能为NULL
 * @param stats 统计信息输出缓冲区，不能为NULL
 * 
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 获取成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 参数为空指针
 * 
 * @note 该函数是线程安全的，使用互斥锁保护共享数据
 * @note 获取的统计信息是当前时刻的快照
 * @see protocol_statemachine_stats_t
 */
protocol_error_t protocol_statemachine_get_stats(protocol_statemachine_handle_t handle, 
                                                protocol_statemachine_stats_t* stats);

/* ==================== 回调设置函数 ==================== */

/**
 * @brief 设置状态变化回调函数
 * @details 设置状态机状态变化时的回调函数。当状态机的主状态或子状态发生变化时，
 *          系统会自动调用此回调函数通知应用程序。应用程序可以在此函数中处理各种
 *          状态变化事件，实现自定义的状态变化处理逻辑。
 * 
 * @param handle 状态机管理器句柄，不能为NULL
 * @param callback 状态变化处理回调函数指针，可以为NULL（表示取消回调）
 * @param user_data 用户数据指针，会传递给回调函数，可以为NULL
 * 
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 设置成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 句柄为空指针
 * 
 * @note 该函数是线程安全的，使用互斥锁保护共享数据
 * @note 如果callback为NULL，则取消状态变化回调
 * @warning 回调函数应该尽快返回，避免阻塞状态机
 * @see protocol_state_callback_t
 * @see protocol_statemachine_set_event_callback
 * @see protocol_statemachine_set_timeout_callback
 */
protocol_error_t protocol_statemachine_set_state_callback(protocol_statemachine_handle_t handle, 
                                                         protocol_state_callback_t callback, 
                                                         void* user_data);

/**
 * @brief 设置事件处理回调函数
 * @details 设置状态机事件处理时的回调函数。当状态机接收到事件时，
 *          系统会自动调用此回调函数通知应用程序。应用程序可以在此函数中处理各种
 *          事件，实现自定义的事件处理逻辑。
 * 
 * @param handle 状态机管理器句柄，不能为NULL
 * @param callback 事件处理回调函数指针，可以为NULL（表示取消回调）
 * @param user_data 用户数据指针，会传递给回调函数，可以为NULL
 * 
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 设置成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 句柄为空指针
 * 
 * @note 该函数是线程安全的，使用互斥锁保护共享数据
 * @note 如果callback为NULL，则取消事件处理回调
 * @warning 回调函数应该尽快返回，避免阻塞状态机
 * @see protocol_event_callback_t
 * @see protocol_statemachine_set_state_callback
 * @see protocol_statemachine_set_timeout_callback
 */
protocol_error_t protocol_statemachine_set_event_callback(protocol_statemachine_handle_t handle, 
                                                         protocol_event_callback_t callback, 
                                                         void* user_data);

/**
 * @brief 设置超时回调函数
 * @details 设置状态机超时发生时的回调函数。当状态机的超时定时器触发时，
 *          系统会自动调用此回调函数通知应用程序。应用程序可以在此函数中处理各种
 *          超时事件，实现自定义的超时处理逻辑。
 * 
 * @param handle 状态机管理器句柄，不能为NULL
 * @param callback 超时处理回调函数指针，可以为NULL（表示取消回调）
 * @param user_data 用户数据指针，会传递给回调函数，可以为NULL
 * 
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 设置成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 句柄为空指针
 * 
 * @note 该函数是线程安全的，使用互斥锁保护共享数据
 * @note 如果callback为NULL，则取消超时回调
 * @warning 回调函数应该尽快返回，避免阻塞状态机
 * @see protocol_statemachine_timeout_callback_t
 * @see protocol_statemachine_set_state_callback
 * @see protocol_statemachine_set_event_callback
 */
protocol_error_t protocol_statemachine_set_timeout_callback(protocol_statemachine_handle_t handle, 
                                                           protocol_statemachine_timeout_callback_t callback, 
                                                           void* user_data);

/* ==================== 超时管理函数 ==================== */

/**
 * @brief 启动协议状态机超时定时器
 * @details 启动指定类型的超时定时器。该函数会设置指定超时类型的启动时间，
 *          超时处理线程会定期检查并触发超时事件。支持T0、T1、T2、T3四种超时类型。
 *          该函数是线程安全的，使用互斥锁保护共享数据。
 * 
 * @param handle 状态机管理器句柄，不能为NULL
 * @param timeout_type 超时类型，取值范围0-3
 *                     - 0: T0超时（连接建立超时）
 *                     - 1: T1超时（发送或测试帧超时）
 *                     - 2: T2超时（确认超时）
 *                     - 3: T3超时（发送或测试帧超时）
 * 
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 启动成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 句柄为空指针
 *         - PROTOCOL_ERROR_INVALID_PARAM: 超时类型无效
 * 
 * @note 该函数是线程安全的，使用互斥锁保护共享数据
 * @note 超时时间由配置参数中的对应值决定
 * @warning 超时类型必须在有效范围内（0-3）
 * @see protocol_statemachine_stop_timeout
 * @see protocol_statemachine_reset_timeout
 */
protocol_error_t protocol_statemachine_start_timeout(protocol_statemachine_handle_t handle, 
                                                    uint32_t timeout_type);

/**
 * @brief 停止协议状态机超时定时器
 * @details 停止指定类型的超时定时器。该函数会清除指定超时类型的启动时间，
 *          使超时处理线程不再检查该类型的超时。支持T0、T1、T2、T3四种超时类型。
 *          该函数是线程安全的，使用互斥锁保护共享数据。
 * 
 * @param handle 状态机管理器句柄，不能为NULL
 * @param timeout_type 超时类型，取值范围0-3
 *                     - 0: T0超时（连接建立超时）
 *                     - 1: T1超时（发送或测试帧超时）
 *                     - 2: T2超时（确认超时）
 *                     - 3: T3超时（发送或测试帧超时）
 * 
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 停止成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 句柄为空指针
 *         - PROTOCOL_ERROR_INVALID_PARAM: 超时类型无效
 * 
 * @note 该函数是线程安全的，使用互斥锁保护共享数据
 * @note 停止后，该类型的超时事件将不再触发
 * @warning 超时类型必须在有效范围内（0-3）
 * @see protocol_statemachine_start_timeout
 * @see protocol_statemachine_reset_timeout
 */
protocol_error_t protocol_statemachine_stop_timeout(protocol_statemachine_handle_t handle, 
                                                   uint32_t timeout_type);

/**
 * @brief 重置协议状态机超时定时器
 * @details 重置指定类型的超时定时器。该函数会重新设置指定超时类型的启动时间，
 *          相当于先停止再启动该超时定时器。支持T0、T1、T2、T3四种超时类型。
 *          该函数是线程安全的，使用互斥锁保护共享数据。
 * 
 * @param handle 状态机管理器句柄，不能为NULL
 * @param timeout_type 超时类型，取值范围0-3
 *                     - 0: T0超时（连接建立超时）
 *                     - 1: T1超时（发送或测试帧超时）
 *                     - 2: T2超时（确认超时）
 *                     - 3: T3超时（发送或测试帧超时）
 * 
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 重置成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 句柄为空指针
 *         - PROTOCOL_ERROR_INVALID_PARAM: 超时类型无效
 * 
 * @note 该函数是线程安全的，使用互斥锁保护共享数据
 * @note 重置会重新开始计时，超时时间由配置参数中的对应值决定
 * @warning 超时类型必须在有效范围内（0-3）
 * @see protocol_statemachine_start_timeout
 * @see protocol_statemachine_stop_timeout
 */
protocol_error_t protocol_statemachine_reset_timeout(protocol_statemachine_handle_t handle, 
                                                    uint32_t timeout_type);

/* ==================== 辅助函数 ==================== */

/**
 * @brief 获取协议状态名称字符串
 * @details 将协议状态枚举值转换为对应的字符串名称，用于日志记录和调试。
 *          该函数返回静态字符串数组中的对应项，返回的字符串指针在程序
 *          运行期间保持有效，不需要释放内存。
 * 
 * @param state 协议状态枚举值
 * 
 * @return 状态名称字符串
 *         - "STOPPED": 停止状态
 *         - "STARTING": 启动状态
 *         - "STARTED": 已启动状态
 *         - "STOPPING": 停止中状态
 *         - "ERROR": 错误状态
 *         - "UNKNOWN": 未知状态（当state值无效时）
 * 
 * @note 返回的字符串指针是静态的，不需要释放内存
 * @note 该函数是线程安全的，只读取静态数据
 * @see protocol_state_t
 * @see protocol_statemachine_get_substate_name
 * @see protocol_statemachine_get_event_name
 */
const char* protocol_statemachine_get_state_name(protocol_state_t state);

/**
 * @brief 获取协议子状态名称字符串
 * @details 将协议子状态枚举值转换为对应的字符串名称，用于日志记录和调试。
 *          该函数返回静态字符串数组中的对应项，返回的字符串指针在程序
 *          运行期间保持有效，不需要释放内存。
 * 
 * @param substate 协议子状态枚举值
 * 
 * @return 子状态名称字符串
 *         - "IDLE": 空闲子状态
 *         - "CONNECTING": 连接中子状态
 *         - "CONNECTED": 已连接子状态
 *         - "DISCONNECTING": 断开中子状态
 *         - "DATA_TRANSFER": 数据传输子状态
 *         - "UNKNOWN": 未知子状态（当substate值无效时）
 * 
 * @note 返回的字符串指针是静态的，不需要释放内存
 * @note 该函数是线程安全的，只读取静态数据
 * @see protocol_substate_t
 * @see protocol_statemachine_get_state_name
 * @see protocol_statemachine_get_event_name
 */
const char* protocol_statemachine_get_substate_name(protocol_substate_t substate);

/**
 * @brief 获取协议事件名称字符串
 * @details 将协议事件枚举值转换为对应的字符串名称，用于日志记录和调试。
 *          该函数返回静态字符串数组中的对应项，返回的字符串指针在程序
 *          运行期间保持有效，不需要释放内存。
 * 
 * @param event 协议事件枚举值
 * 
 * @return 事件名称字符串
 *         - "START": 启动事件
 *         - "STOP": 停止事件
 *         - "CONNECT": 连接事件
 *         - "DISCONNECT": 断开事件
 *         - "DATA_RECEIVED": 数据接收事件
 *         - "DATA_SENT": 数据发送事件
 *         - "TIMEOUT": 超时事件
 *         - "ERROR": 错误事件
 *         - "UNKNOWN": 未知事件（当event值无效时）
 * 
 * @note 返回的字符串指针是静态的，不需要释放内存
 * @note 该函数是线程安全的，只读取静态数据
 * @see protocol_event_t
 * @see protocol_statemachine_get_state_name
 * @see protocol_statemachine_get_substate_name
 */
const char* protocol_statemachine_get_event_name(protocol_event_t event);

/**
 * @brief 验证协议状态机配置参数的有效性
 * @details 验证协议状态机配置参数是否符合104协议的要求和系统限制。
 *          该函数会检查所有必要的配置参数，确保它们的值在有效范围内。
 *          验证包括超时时间、K值、W值、重试次数等关键参数的合理性检查。
 * 
 * @param config 待验证的状态机配置参数，不能为NULL
 * 
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 配置验证通过
 *         - PROTOCOL_ERROR_NULL_POINTER: 配置参数为空指针
 *         - PROTOCOL_ERROR_INVALID_PARAM: 配置参数无效
 * 
 * @note 该函数是线程安全的，只读取配置数据
 * @note 验证规则：
 *       - 超时时间必须大于0
 *       - K值必须在1-32767范围内
 *       - W值必须在1-32767范围内
 *       - 最大重试次数必须大于0
 * @see protocol_statemachine_config_t
 * @see protocol_statemachine_create
 */
protocol_error_t protocol_statemachine_validate_config(const protocol_statemachine_config_t* config);

#ifdef __cplusplus
}
#endif

#endif /* PROTOCOL_STATEMACHINE_H */
